<?php
namespace Pinenut;

/**
 * Логирование и профилирование
 * 
 * Для профилирования нужно поименовать группу, в рамках которой 
 * идёт профилирование begin-end
 * 
 *
 */
abstract class Log {
	
	const LOG = 'log';
	const INFO = 'info';
	const WARN = 'warn';
	const ERROR = 'error';
	
	static protected $_timeStack = [];
	static protected $_profileStack = [];
	static protected $_profileLevels = [];
	static protected $_titleStack = [];
	
	abstract static protected function beginGroup($title = null);
	abstract static protected function endGroup();
	abstract static protected function commit($title, $data = null, $level = 'log', $file = "", $line = 0, $beginTime = null, $endTime = null);
	abstract static protected function profile($group, $beginTime, $endTime, $title, $data = null, $level = 0);
	
	/**
	 * Начинаем отсчет-группу
	 * @param string $title
	 * @param string $profileGroup
	 */
	static function begin($title = null, $profileGroup = null) {
		if (!\Application::isDebug())
			return;
		
		static::$_timeStack[] = microtime(true);
		static::$_profileStack[] = $profileGroup;
		@static::$_profileLevels[$profileGroup]++;
		static::$_titleStack[] = $title;
		
		// отмечаем начало группы
		if ($title) {
			static::beginGroup($title);
		}
		
	}
	
	/**
	 * Заканчиваем отсчет-группу
	 * @param string $title
	 * @param string $data
	 */
	static function end($title = null, $data = null) {
		if (!\Application::isDebug())
			return;		

		
		$time = array_pop(static::$_timeStack);
		$profileGroup = array_pop(static::$_profileStack);
		$level = @static::$_profileLevels[$profileGroup]--;
		$beginTitle = array_pop(static::$_titleStack);
		
		// если нашли группу для профилирования - заканчиваем её
		if (null !== $profileGroup) {
			static::profile($profileGroup, $time, microtime(true), (!empty($title)?$title:$beginTitle), $data, $level);
		}
		
		// оканчиваем группу
		if ($beginTitle) {
			static::endGroup ();
		} else {
			static::commit($title, $data, null, null, null, $time, microtime(true));
		}
			
	}
	/**
	 * Размещаем сообщение
	 * 
	 * @param string $title
	 * @param mixed $data
	 * @param string $level
	 * @param number $step для отображения адреса вызова нужно указать сколько вызовов назад случилось событие
	 */
	static function msg($title, $data = null, $level = 'log', $step = 0) {
		if (!\Application::isDebug())
			return;
		
		$debug = debug_backtrace ();
		static::commit ($title, $data, $level, @$debug [$step] ['file'], @$debug [$step] ['line'] );
	}
	/**
	 * Информационное сообщение
	 * @param string $title
	 * @param mixed $data
	 */
	static function info($title, $data = null) {
		static::msg($title, $data, static::INFO, 1);
	}
	/**
	 * Предупреждение
	 * @param string $title
	 * @param mixed $data
	 */
	static function warn($title, $data = null) {
		static::msg($title, $data, static::WARN, 1);
	}
	/**
	 * Ошибка
	 * @param string $title
	 * @param mixed $data
	 */
	static function error($title, $data = null) {
		static::msg($title, $data, static::ERROR, 1);
	}
	
	/**
	 * После выполнения запроса - делаем что нужно...
	 */
	static function onFinish() {}
}